package edu.kit.aifb.ruleintegrator.repository;

import java.util.ArrayList;
import java.util.List;

import org.semanticweb.yars.nx.Resource;
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Represent;
import org.yaml.snakeyaml.representer.Representer;



public class RSRepresenter extends Representer{
	    public RSRepresenter() {
	        this.representers.put(RepositoryStatistics.class, new RepresentRS());
	    }

	    private class RepresentRS implements Represent {
	        public Node representData(Object data) {
	            RepositoryStatistics rs = (RepositoryStatistics) data;
//	            String value = rs..getA() + "d" + dice.getB();
	            
//	            return representScalar(new Tag("!dice"), value);
	           return representRS(rs);

	        }
	        
	        protected Node representRS(RepositoryStatistics rs){
	        	 Tag tag=
		            new Tag(rs.getClass());
	        	 List<NodeTuple> value = new ArrayList<NodeTuple>(1);
	        	 
	        	 MappingNode node=new MappingNode(tag, value, null);
	        	 representedObjects.put(rs,node);
	        	 
	        	 NodeTuple attTuple = representAttributes(rs);
	        	 value.add(attTuple);
	        	 NodeTuple relTuple = representRelations(rs);
	        	 value.add(relTuple);
	        	 NodeTuple clsTuple = representClasses(rs);
	        	 value.add(clsTuple);
	        	 NodeTuple clsStatTuple=representClassStats(rs);
	        	 value.add(clsStatTuple);
	        	 NodeTuple relStatTuple=representRelationStats(rs);
	        	 value.add(relStatTuple);

	        	  if (defaultFlowStyle != FlowStyle.AUTO) {
	                  node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
	              } else {
	                  node.setFlowStyle(true);
	              }

	        	 return node;

	        }

			private NodeTuple representAttributes(RepositoryStatistics rs) {
				// TODO Auto-generated method stub
				ScalarNode key=new ScalarNode(Tag.STR, "attributes", null, null, null);
				Node sq=representResources(rs.getAttributeList());
				return new NodeTuple(key,sq);
			} 
			
			private NodeTuple representRelations(RepositoryStatistics rs) {
				// TODO Auto-generated method stub
				ScalarNode key=new ScalarNode(Tag.STR, "relations", null, null, null);
				Node sq=representResources(rs.getRelationList());
				return new NodeTuple(key,sq);
			} 
			
			private NodeTuple representClasses(RepositoryStatistics rs) {
				// TODO Auto-generated method stub
				ScalarNode key=new ScalarNode(Tag.STR, "classes", null, null, null);
				Node sq=representResources(rs.getClassList());
				return new NodeTuple(key,sq);
			} 
			
			private NodeTuple representRelationStats(RepositoryStatistics rs){
				ScalarNode key=new ScalarNode(new Tag(RelationStats.class),"relstats",null,null,null);
				Tag tag=Tag.MAP;
				List<NodeTuple> value=new ArrayList<NodeTuple>(rs.m_relationStats.size());
				MappingNode node=new MappingNode(tag, value, null);
				for(Resource rel:rs.m_relationStats.keySet()){
					Node relKey= representResource(rel);
					Node relNode=representRelationStat(rs.getRelationStats(rel));
					value.add(new NodeTuple(relKey,relNode));
				}
				return new NodeTuple(key,node);
			}
			
			private Node representRelationStat(RelationStats rss){
				Tag tag=new Tag(RelationStats.class);
				List<NodeTuple> value=new ArrayList<NodeTuple>(6);

				MappingNode node=new MappingNode(tag,value,null);

				ScalarNode sck=new ScalarNode(Tag.STR,"sourceclasses",null,null,null);
				Node scn=representResources(rss.getSourceClasses());
				value.add(new NodeTuple(sck,scn));
				
				ScalarNode tck=new ScalarNode(Tag.STR,"targetclasses",null,null,null);
				Node tcn=representResources(rss.getTargetClasses());
				value.add(new NodeTuple(tck,tcn));
				
				ScalarNode srk=new ScalarNode(Tag.STR,"sourcerelations",null,null,null);
				Node srn=representResources(rss.getSourceRelations());
				value.add(new NodeTuple(srk,srn));

				ScalarNode trk=new ScalarNode(Tag.STR,"targetrelations",null,null,null);
				Node trn=representResources(rss.getTargetRelations());
				value.add(new NodeTuple(trk,trn));

				ScalarNode sak=new ScalarNode(Tag.STR,"sourceattributes",null,null,null);
				Node san=representResources(rss.getSourceAttributes());
				value.add(new NodeTuple(sak,san));

				ScalarNode tak=new ScalarNode(Tag.STR,"targetattributes",null,null,null);
				Node tan=representResources(rss.getTargetAttributes());
				value.add(new NodeTuple(tak,tan));

				return node;
			}
	
			private NodeTuple representClassStats(RepositoryStatistics rs){
				ScalarNode key=new ScalarNode(new Tag(ClassStats.class),"clsstats",null,null,null);
				Tag tag=Tag.MAP;
				List<NodeTuple> value=new ArrayList<NodeTuple>(rs.m_clsStats.size());
				MappingNode node=new MappingNode(tag, value, null);
				for(Resource cls:rs.m_clsStats.keySet()){
					Node clsKey= representResource(cls);
					Node clsNode=representClassStat(rs.m_clsStats.get(cls));
					value.add(new NodeTuple(clsKey,clsNode));
				}
				return new NodeTuple(key,node);
			}

			private Node representClassStat(ClassStats css){
				Tag tag=new Tag(ClassStats.class);
				List<NodeTuple> value=new ArrayList<NodeTuple>(2);

				MappingNode node=new MappingNode(tag,value,null);
				
				ScalarNode srk=new ScalarNode(Tag.STR,"sourcerelatoins",null,null,null);
				Node srn=representResources(css.getRelations());
				value.add(new NodeTuple(srk,srn));
				
				ScalarNode sak=new ScalarNode(Tag.STR,"sourceattributes",null,null,null);
				Node san=representResources(css.getAttributes());
				value.add(new NodeTuple(sak,san));
	

				return node;
			}
			
			private Node representResources(List<Resource> ress){
				Tag tag=Tag.SEQ;
				List<Node> value=new ArrayList<Node>(ress.size());
				SequenceNode sq=new SequenceNode(tag, value, null);
				for(Resource rel:ress){
					value.add(representResource(rel));
				}
				return sq;
			}
			
			private Node representResource(Resource res){
				
			        ScalarNode node=new ScalarNode(new Tag(Resource.class), res.toN3(), null, null, null);
//			        ScalarNode n3=new ScalarNode(Tag.STR, res.toN3(), null, null, null);
					
        
			        return node;				
			}
	    }
}
